package com.ecoolex.ying.space.api.graphql;

import com.ecoolex.framework.common.enums.ResultCode;
import com.ecoolex.framework.common.pojo.Page;
import com.ecoolex.framework.common.pojo.Pagination;
import com.ecoolex.framework.common.pojo.Sorting;
import com.ecoolex.framework.common.util.BizAssert;
import com.ecoolex.framework.common.util.Check;
import com.ecoolex.framework.modularize.api.auth.user.ConsumerMember;
import com.ecoolex.framework.modularize.api.auth.user.ConsumerMemberAuthority;
import com.ecoolex.framework.modularize.api.auth.user.ConsumerMemberManager;
import com.ecoolex.framework.web.api.graphql2.annotation.GraphQL2Module;
import com.ecoolex.framework.web.api.graphql2.annotation.MutationField;
import com.ecoolex.framework.web.api.graphql2.annotation.QueryField;
import com.ecoolex.framework.web.api.graphql2.annotation.Source;
import com.ecoolex.framework.web.api.graphql2.annotation.TypeField;
import com.ecoolex.ying.space.entity.UserIdentityAuthentication;
import com.ecoolex.ying.space.entity.UserWatch;
import com.ecoolex.ying.space.enums.UserIdentityAuthenticationDomainType;
import com.ecoolex.ying.space.pojo.AddUserWatchDTO;
import com.ecoolex.ying.space.pojo.QueryUserWatchDTO;
import com.ecoolex.ying.space.pojo.QueryUserWatchFansDTO;
import com.ecoolex.ying.space.ws.UserIdentityAuthenticationService;
import com.ecoolex.ying.space.ws.UserInfoExtService;
import com.ecoolex.ying.space.ws.UserWatchService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.NonNull;


@GraphQL2Module(type = GraphQL2Module.Type.User, description = "关注")
public class UserWatchGraphql {

    @Reference
    UserWatchService userWatchService;

    @Reference
    private UserInfoExtService userInfoExtService;

    @Autowired
    private ConsumerMemberManager consumerMemberManager;

    @Reference
    private UserIdentityAuthenticationService userIdentityAuthenticationService;

    @TypeField(type = ConsumerMember.class,
        field = "watchOperateType",
        description = { "关注操作",
            "0: 啥也不能干; 1: 能关注; 2: 能取消关注;" })
    public int watchOper(@Source ConsumerMember source, ConsumerMemberAuthority user) {
        if (!user.isLogin()) {
            return 1;
        }
        if (source.getUserId().equals(user.userId())) {
            return 0;
        }
        UserWatch watch = userWatchService.getUserWatchByTwoUserId(user.userId(), source.getUserId());
        if (Check.isNull(watch)) {
            return 1;
        }
        UserIdentityAuthentication userIdentityAuthentication
            = userIdentityAuthenticationService.getByUserId(source.getUserId());

        return Check.isNull(userIdentityAuthentication) ? 2
            : 0;
    }

    @QueryField(field = "recommendWatchList", description = "推荐关注列表")
    public Pagination<ConsumerMember> recommendWatchList(String keyword, @NonNull Page page, ConsumerMemberAuthority user) {
        user.assertLogin();

        Pagination<Integer> result = userInfoExtService.queryRecommendWatchUser(keyword, user.userId(), page);
        return Pagination.create(page,
            result.getTotalCount(),
            consumerMemberManager.queryByUserIdList(result.getList()));
    }

    @QueryField(field = "myUserWatchCount", description = "我的关注数量")
    public Long myUserWatchCount(ConsumerMemberAuthority user) {
        user.assertLogin();
        return userWatchService.watchCount(user.userId());
    }

    @QueryField(field = "myUserFansCount", description = "我的粉丝数量")
    public Long myUserFansCount(ConsumerMemberAuthority user) {
        user.assertLogin();
        return userWatchService.FansCount(user.userId());
    }

    @QueryField(field = "myUserWatchList", description = "我的关注列表")
    public Pagination<ConsumerMember> queryWatchList(@NonNull QueryUserWatchDTO query, @NonNull Sorting[] sorts, @NonNull Page page, ConsumerMemberAuthority user) {
        user.assertLogin();
        return userWatchService.queryWatchList(user.userId(), query, sorts, page);
    }

    @QueryField(field = "myUserFansList", description = "我的粉丝列表")
    public Pagination<ConsumerMember> queryFansList(@NonNull QueryUserWatchFansDTO query, @NonNull Sorting[] sorts, @NonNull Page page, ConsumerMemberAuthority user) {
        user.assertLogin();
        return userWatchService.queryFansList(user.userId(), query, sorts, page);
    }

    @QueryField(field = "otherUserWatchCount", description = "他人关注数量")
    public Long otherUserWatchCount(@NonNull Integer userId) {
        return userWatchService.watchCount(userId);
    }

    @QueryField(field = "otherUserFansCount", description = "他人粉丝数量")
    public Long otherUserFansCount(@NonNull Integer userId) {
        return userWatchService.FansCount(userId);
    }

    @QueryField(field = "otherUserWatchList", description = "他人关注列表")
    public Pagination<ConsumerMember> queryOtherWatchList(@NonNull Integer userId, @NonNull QueryUserWatchDTO query, @NonNull Sorting[] sorts, @NonNull Page page) {
        return userWatchService.queryWatchList(userId, query, sorts, page);
    }

    @QueryField(field = "otherUserFansList", description = "他人粉丝列表")
    public Pagination<ConsumerMember> queryOtherFansList(@NonNull Integer userId, @NonNull QueryUserWatchFansDTO query, @NonNull Sorting[] sorts, @NonNull Page page) {
        return userWatchService.queryFansList(userId, query, sorts, page);
    }

    @MutationField(field = "watchUser", description = "关注某个用户")
    public ConsumerMember watch(@NonNull AddUserWatchDTO add, ConsumerMemberAuthority user) {
        user.assertLogin();
        add.setUserId(user.userId());

        BizAssert.isTrue(Check.notEq(add.getUserId(), add.getWatchUserId()), ResultCode.VERIFY.build(1), "不能关注自己");
        ConsumerMember consumerMember = consumerMemberManager.getByUserId(add.getWatchUserId());
        BizAssert.isTrue(Check.notNull(consumerMember), ResultCode.VERIFY.build(2), "关注的用户不存在");

        UserWatch old = userWatchService.getUserWatchByTwoUserId(add.getUserId(), add.getWatchUserId());
        if (Check.isNull(old)) {
            userWatchService.addUserWatch(add, user.userName());
        }
        return consumerMember;
    }

    @MutationField(field = "unwatchUser", description = "取消关注某个用户")
    public ConsumerMember unwatch(@NonNull Integer watchUserId, ConsumerMemberAuthority user) {
        user.assertLogin();
        // 不能取消官方账号
        UserIdentityAuthentication userIdentityAuthentication
            = userIdentityAuthenticationService.getByUserId(watchUserId);
        BizAssert.isTrue(
            Check.isNull(userIdentityAuthentication) || UserIdentityAuthenticationDomainType.OFFICIALPLATFORM.notEqual(
                userIdentityAuthentication.getDomainType()),
            ResultCode.VERIFY.build(2),
            "无法取消关注官方账号");
        UserWatch userWatch = userWatchService.getUserWatchByTwoUserId(user.userId(), watchUserId);
        BizAssert.isTrue(Check.notNull(userWatch), ResultCode.VERIFY.build(3), "关注数据不存在");
        userWatchService.deleteUserWatch(userWatch, user.userName());
        return consumerMemberManager.getByUserId(watchUserId);
    }

}
